package com.example.sonone.xianliusuanfa;

import java.util.LinkedList;
import java.util.Random;

/**
 * 滑动时间窗口限流实现
 * 假设某个服务最多只能每秒钟处理10个请求，我们可以设置一个1 秒钟的滑动时间窗口，
 * 窗口中有10个格子，每个格子100毫秒，每100毫秒移动一次，每次移动都需要记录当前服务请求的次数
 */
public class SlidingTimeWindow {

    //服务访问次数，可以放在Redis中，实现分布式系统的访问计数
    Long counter = 0L;
    //使用LinkedList来记录滑动窗口的10个格子。
    LinkedList<Long> slots = new LinkedList<Long>();

    boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        SlidingTimeWindow timeWindow = new SlidingTimeWindow();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    timeWindow.doCheck();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }).start();
        while (true) {
//            //TODO 判断限流标记
            timeWindow.counter++;
            Thread.sleep(new Random().nextInt(10));
        }
    }

    private void doCheck() throws InterruptedException {
        while (true) {
            slots.addLast(counter);
            if (slots.size() > 10) {            // 超过10个g格子
                slots.removeFirst();            // 清除掉第一个
            }
            //比较最后一个和第一个，两者相差100以上就限流
            if ((slots.peekLast() - slots.peekFirst()) > 100) {
                System.out.println("限流了。。");
                //TODO 修改限流标记为true
                flag = true;

            } else {
                System.out.println("木有   限流了。。");
                //TODO 修改限流标记为false
                flag = true;
            }
            Thread.sleep(100);
        }

    }


}
